/*
 * encPacketHandler.h
 *
 * Created: 6/13/2013 3:02:03 AM
 *  Author: Tim
 */ 


#ifndef ENCPACKETHANDLER_H_
#define ENCPACKETHANDLER_H_
#include <stdbool.h>
#include "../status.h"
#include "../../features/tmr/tmr.h"
#include <avr/io.h>

#include "../structs/encPacketStructs.h"

#include "../../features/enc/enc.h"

#include "../../features/tmr/tmr.h"

#include "../CRC.h"

#include "../structs/msgHeaderDefs.h"

#include "../../communication/comPort.h"

#include "../../board/board.h"

static inline status_t encInitAsyncHandler(encInitAsync_t *packet)
{
	
	tmrAlloc_t encTmr, intTmr;
	
	if(daqAlloc.standAlone.daqStandAlone) return OPP_FAILED;//this function is not standalone type
	
	//make sure the pin locations are available for an encoder
	if(encCheckPLOC((encInitAsync_t *)packet) == OPP_FAILED)				return OPP_FAILED;
	
	//find the next free timer in line
	encTmr = tmrCheckAvailability();
	
	//if all timers are already utilized jump ship
	if (encTmr == TIMER_NULL)										return OPP_FAILED;
	//allocate the timer
	allocTimer(encTmr);
	
	//search for a timer of the same frequency
	intTmr = tmrCheckFrequency(packet->PARAM4.EFRQ);
	
	//check to see if a timer of the same frequency exists
	if(intTmr == TIMER_NULL) 
	{
		//search for a free timer
		intTmr = tmrCheckAvailability();
		if (intTmr == TIMER_NULL)
		{
			//release encTmr since there are not enough system resources
			unAllocTimer(encTmr);
			return OPP_FAILED;
		}
		else
		{
			//if the timer was free we need to configure it
			tmrSetupFreq(intTmr,packet->PARAM4.EFRQ);
		}
	}
	 
	//this alloc is used by the interrupt handler
	daqAlloc.enc_int[packet->PARAM1.ENCN] = intTmr;
	//setup the encoder
	encSetup((encInitAsync_t *)packet,encTmr);
	
	return OPP_SUCCESSFUL;
}

//there are two types of timers however the registers we care about are identical for both
static inline status_t encCurCountHandler(bool encoderNumber)
{
	encCurCount_t packet;
	
	tmrAlloc_t tmrDef;
	
	uint16_t encoderVal;
	
	if (encoderNumber)	tmrDef = daqAlloc.encAlloc.enc1TmrAlloc;
	else				tmrDef = daqAlloc.encAlloc.enc0TmrAlloc;
	
	switch(tmrDef)
	{
		case TIMER_C0:
			encoderVal = TCC0.CNT;
			packet.PARAM1.ENCD = TCC0.CTRLFSET & TC0_DIR_bm;//all good because dir is in the bit 0 location of ctrlfxxx
			TCC0.CNT = 0;
		break;
		case TIMER_C1:
			encoderVal = TCC1.CNT;
			packet.PARAM1.ENCD = TCC1.CTRLFSET & TC1_DIR_bm;//all good because dir is in the bit 0 location of ctrlfxxx
			TCC1.CNT = 0;
		break;
		case TIMER_D0:
			encoderVal = TCD0.CNT;
			packet.PARAM1.ENCD = TCD0.CTRLFSET & TC0_DIR_bm;//all good because dir is in the bit 0 location of ctrlfxxx
			TCD0.CNT = 0;
		break;
		case TIMER_D1:
			encoderVal = TCD1.CNT;
			packet.PARAM1.ENCD = TCD1.CTRLFSET & TC1_DIR_bm;//all good because dir is in the bit 0 location of ctrlfxxx
			TCD1.CNT = 0;
		break;
		case TIMER_E0:
			encoderVal = TCE0.CNT;
			packet.PARAM1.ENCD = TCE0.CTRLFSET & TC0_DIR_bm;//all good because dir is in the bit 0 location of ctrlfxxx
			TCE0.CNT = 0;
		break;
	}
	
	packet.Header = packetHeader;
	packet.msgHeader = encCurCount_mh;
	
	packet.PARAM1.ENCCH = (0xFF00 & encoderVal)>>8;
	packet.PARAM1.ENCN = encoderNumber;
	
	packet.PARAM2.ENCCL = 0x00FF & encoderVal;
	
	crcAppend(&packet,packetSizeLookup(encCurCount_mh));
	comPortPut(&packet,packetSizeLookup(encCurCount_mh));
	return OPP_SUCCESSFUL;
}

#endif /* ENCPACKETHANDLER_H_ */